package dao;

import util.DruidDataSourceUtil;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;

/**
 * 通用的工具类
 */
public class BaseDao {

    /**
     *
     * @param sql
     * @param param
     * @return
     */
    public int executeUpdate(String sql, Object... param) {
        int result = 0;
        try {
            // 1. 通过 连接池工具类 获取连接对象
            Connection c = DruidDataSourceUtil.getDruidDataSource();
            // 2. 预编译 SQL 语句
            PreparedStatement prepared = c.prepareStatement(sql);
            // 3.为占位符赋值
            for (int i = 0; i < param.length; i++) {
                prepared.setObject(i + 1, param[i]);
            }
            // 执行结果
            result = prepared.executeUpdate();
            // 释放资源
            c.close();
        }catch (Exception e) {
            System.out.println(e.getMessage());
        }

        return result;
    }

    /**
     * 查询的通用方法
     *      查到很多条数据 List<Obj></>
     *      查到一条数据
     * 封装过程
     *      1. 返回的类型：返现 因为类型不确定，调用者知道，在调用的时候告诉 BaseDAO 即可
     *      2. 返回的结果 通用的 List
     *      3. 结果的封装 使用反射
     */
    public <T> List<T> executeQuery(Class<T> clazz, String sql, Object... param) {

        List<T> list = new ArrayList<T>();
        try {
            // 1. 通过 连接池工具类 获取连接对象
            Connection c = DruidDataSourceUtil.getDruidDataSource();
            // 2. 预编译 SQL 语句
            PreparedStatement prepared = c.prepareStatement(sql);
            // 3.为占位符赋值
            for (int i = 0; i < param.length; i++) {
                prepared.setObject(i + 1, param[i]);
            }
            ResultSet resultSet = prepared.executeQuery();
            // 获取结果集中的元素数据对象
            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();

            while (resultSet.next()) {
                // 循环一次就代表有一条数据 使用反射创建一个对象
                T t = clazz.newInstance();
                for (int i = 1; i <= columnCount; i++) {
                    Object value = resultSet.getObject(i);
                    String fileName = metaData.getColumnLabel(i);

                    // 获取当前拿到的列的名称 匹配对象的属性
                    Field field = clazz.getDeclaredField(fileName);
                    // 设置属性值
                    field.setAccessible(true); // 暴力反射
                    field.set(t, value);
                }

                // 上面代码每循环一次封装一个对象
                list.add(t);
            }

            // 关闭资源
            resultSet.close();
            prepared.close();
            c.close();

        }catch (Exception e) {
            System.out.println(e.getMessage());
        }

        return list;
    }
}
